
{***********************************************************}
{                                                           }
{      Informix esql "collect.h"                            }
{                                                           }
{      Translated to Object Pascal by                       }
{      Copyright (c) 2001-2008 Luxena Software Company      }
{      http://www.luxena.com                                }
{      e-mail: support@luxena.com                           }
{                                                           }
{***********************************************************}

unit IfxCollect;

{$I lx.inc}

{$IFDEF VER140_OR_ABOVE}
  {$ALIGN 8}
{$ENDIF}

interface

uses
  LXTypes, IfxTypes, IfxDecimal, IfxLocator, IfxBlob, IfxInt8, IfxDateTime,
  IfxStubUnit;

const
  // special position value IFX_COLL_USE_CURSOR_POSITION
  IFX_COLL_USE_CURSOR_POSITION = -5999;

  // size of the identifier. SHOULD BE SAME AS IN THE SERVER.
{$IFNDEF IDENTSIZE}
  IDENTSIZE = 128;
{$ENDIF}

  {------------------------------------------------------------------------------}
  // Value consts

  MAXADDR = 14;

  // flags for td_rowflags
  TD_ROWREF = $00000001;                          // to be REFed, keep fragid and rowid
  TD_ROWTYPE = $00000002;                         // row is typed
  TD_ROWLOCAL = $00000004;                        // row data is in td_row
  TD_ROWDYNA = $00000008;                         // row value in sqt_dtab
  TD_ROWSAVED = $00000010;                        // row in save set
  TD_ROWCONV = $00000020;                         // binary or ascii conv. required
  TD_ROWBINARY = $00000040;                       // binary result requested
  TD_ROWCMDDUR = $00000080;                       // Indicates that the row descriptor is allocated in PER_COMMAND dur.


  TD_ROWSTMTDUR = $00000100;                      // Indicates that the row descriptor is allocated in PER_STATEMENT dur.

  TD_ROWDESTROY = $80000000;                      // processing rowdestroy


  // flag to switch_rowtype() on whether to create the rowdesc
  // and how to link it with existing cd_rowdesc chain

  R_NCREATE = 0;                                  // Flag error if rowdesc does not exist in td_child list

  R_LTAIL = 1;                                    // If created now, link to tail of list
  R_LHEAD = 2;                                    // Put rowdesc at the head of the list




  // flags for v_flags (For FE programs)
  // used by the 4GL Debugger and Pcode Run Time

  V_BREAK = $1;                                   // break when variable is updated
  V_SUBSTR = $2;                                  // char value is a substring
  V_QUOTED = $4;                                  // char value is from quoted string
  V_ASCII0 = $8;                                  // ascii 0 value


  // flags for v_flags (For BE programs)
  // used for FS_[N]SEARCH patterns

  V_FSANSIESCWARN = $1;                           // Fixed string contained a non-ANSI escape sequence in an non-ANSI database
  V_NOHASH = $2;                                  // UDT not hashable
  V_FIXED = $4;                                   // UDT is fixed length (SQLROW type only)
  V_BYVAL = $8;                                   // UDT is by value
  V_QUAL = $10;                                   // v_char contains qualifier (used with char type on client, and SQLUDTVAR (XID_LVARCHAR) type on server)


  // This flag is used in rvaldata(), but mainly used by the FE to null
  // terminate the SQLCHAR data rather than blank padding it as for normal
  // SQLCHAR column.

  V_NTERM = $20;                                  // null terminated the SQLCHAR data




type

  chlog_type = (CH_INSERT, CH_UPDATE, CH_DELETE, CH_CLDATA);
  Tchlog_type = chlog_type;

  // this structure is used when a DML is performed on a collection to store
  // the change.

  PIfx_changelog_struct = ^ifx_changelog_struct;

  ifx_changelog_struct = record
    ch_rownum: mint;                              // row number
    ch_modtype: chlog_type;                       // modification type
    ch_newrow: PChar;                             // pointer to new row
    ch_newrowlen: mint;                           // new row length
    ch_flag: mint;                                // is changelog associated with data?
    ch_next: PIfx_changelog_struct;               // next pointer
    ch_maxrowlen: mint;                           // actual allocated size
  end;

  PIfx_changelog = ^TIfx_changelog;
  TIfx_changelog = ifx_changelog_struct;


  // This can be extended later to support other kinds iterator collections

  ifx_coll_iter = record
    subq_expr: Pointer;
  end;
  PIfx_coll_iter = ^TIfx_coll_iter;
  TIfx_coll_iter = ifx_coll_iter;


  // note: whenever members are added/changed in ifx_collection_struct
  // remember to update ifx_coll_copy().

  PIfx_coll_cur = ^TIfx_coll_cur;
  PIfx_cltypeinfo = ^TIfx_cltypeinfo;

  _ifx_collection_struct = record
    cl_magic: mint;                               // see CL_MAGIC
    cl_handle: mint;                              // 0 if collection is
    // procesed on client
    // !0 if processed on server

    cl_curs: PIfx_coll_cur;                       // cursors specific data for all cursors
    // declared on this collection.

    cl_len: mint;                                 // length of the collection. This at
    // any time will maintain the total
    // length required to hold
    // the collection

    cl_cardinality: mint;                         // #of elements in the collection
    cl_isfixed: int2;                             // 1 if elements are fixed size
    // 0 otherwise.

    cl_elsize: mint;                              // size of each element,if fixed size.
    // otherwise, size of the fixed part

    cl_flags: mint;                               // flags
    cl_lastlog: PIfx_changelog;                   // Last log entry;to make append easy
    cl_log: PIfx_changelog;                       // list of change log structures

    cl_val: record
      case SmallInt of
        0: (cldata: PChar; );                     // actual collection column as retrieved from RSAM
        1: (cliter: PIfx_coll_iter);              // opaque structure for iterator collections
    end;

    // NOTE: cl_hashvalue must be an unsigned 32-bit integer.
    // on 16-bit platform, use unsigned long for cl_hashvalue
    cl_hashvalue: muint;                          // hash value
    cl_datalen: mint;                             // length of the data. This is the

    // the length of the data field when
    // the collection_t was first built
    cl_typed: int2;                               // 1 if type defined explicitly
    cl_typelen: mint;                             // length of below pointer
    cl_svr_typeinfo: PIfx_cltypeinfo;             // Type information provided
    // by the server.

    cl_typeinfo: PIfx_cltypeinfo;                 // Type information returned by
    // the server. or defined by user

    cl_heap: PHeap;                               // indicates the heap from which cldata
    // and chlogs are allocated when the
    // collection is initially created.
    // note: in some cases, cldata may be
    //   allocated from outside the collctn

    cl_freelst: PIfx_changelog;                   // sorted free list of change logs
    // it may be more efficient to use a
    // binary search tree for the freelst

    cl_data_hdr: PIfx_changelog;                  // info about the cl_data in use
  end;

  PPIfx_collection = ^PIfx_collection;
  PIfx_collection = ^TIfx_collection;
  TIfx_collection = _ifx_collection_struct;


  // this is the structure every one registers with a collection manager

  ifx_coll_cur_struct = record
    cur_position: mint;                           // position number
    cur_elem: PChar;                              // pointer to the current row in
    // the data part

    cur_row: PChar;                               // current row to be updated client collections need this
    cur_coll: PIfx_collection;                    // current collection
    cur_changelog: PIfx_changelog;                // current change log entry
    cur_flags: int2;                              // for internal use only
    cur_next: PIfx_coll_cur;                      // for use of collection manager
    cur_run: mint;                                // for internal use only
  end;

  TIfx_coll_cur = ifx_coll_cur_struct;


  // this is the structure that maps to one row of SYSATTR system table
  ifx_typerow_struct = record
    seqno: int2;
    level_no: int2;
    parent_no: int2;
    fieldnmlen: int2;

    fieldname: array[0..IDENTSIZE] of Char;

    field_no: int2;
    AType: int2;
    length: int2;

    xid: int4;

    flags: int2;
    xtype_nm_len: int2;
    xtype_name: array[0..IDENTSIZE - 1] of Char;
    xtype_owner_len: int2;
    xtype_owner_name: array[0..IDENTSIZE - 1] of Char;
    alignment: int2;
    sourcetype: int4;
  end;
  PIfx_typerow = ^TIfx_typerow;
  TIfx_typerow = ifx_typerow_struct;

  // this is the structure that holds the type information for a collection
  ifx_cltypeinfo_struct = record

    // clt_datumbuf, used to return datums, keep 1st to align.
    clt_datumbuf: array[0..19] of Double;

    // full type info for udt/collections this is a ddxtype_t
    clt_ddxtype: Pointer;

    clt_typeid: int4;                             // type id
    clt_namelen: int2;                            // length of the type name
    clt_typename: array[0..IDENTSIZE - 1] of Char;    // name of the type
    clt_numrows: int2;                            // number of rows

    // THIS LINE HAS TO BE LAST DO NOT ADD ANYTHING AFTER IT
    clt_rows: array[0..0] of TIfx_typerow;        // to make this struct contiguous
  end;

  TIfx_cltypeinfo = ifx_cltypeinfo_struct;


  // Since collections are of variable size, each tuple can be of variable
  // size. This structure holds the size of each tuple in the tuple buffer.

  ifx_cl_tupinfo = record
    cti_current: mint;                            // current tuple
    cti_totalsize: mint;                          // total tuple size
    cti_maxsize: mint;                            // maximum array size
    cti_tuplesize: array[0..0] of mint;           // array containing each tuple size
  end;

  PIfx_cl_tupinfo = ^TIfx_cl_tupinfo;
  TIfx_cl_tupinfo = ifx_cl_tupinfo;


  // This structure is used to record the names of the columns
  // in the projection list of an SQL statement.
  ifx_namelist = record
    col_name: array[0..149] of Char;
  end;

  PIfx_namelist = ^TIfx_namelist;
  TIfx_namelist = ifx_namelist;


  // This structure is used to insert data into the collection variable
  ifx_literal = record
    litaddr: PChar;                               // address of host variable
    littype: int2;                                // host type
    litlen: int2;                                 // length of field type
    litqual: int2;                                // qualifier for DATETIME/INTERVAL
    literal: int2;                                // 1 if literal string 0 otherwise
  end;

  PIfx_literal = ^TIfx_literal;
  TIfx_literal = ifx_literal;

  //--------------------------------------------------------------------
    //   used within value_t to store a tree of value_t.
    //   For example,
    //   the value_t tree for SET{1,2,3} looks like the following:
    //
    //   value_t(SET)
    //       --(ct_child)--> value_t(1)
    //                         --(v_next)--> value_t(2)
    //                                          --(v_next)--> value_t(3)
  //--------------------------------------------------------------------

  PValue = ^TValue;

  TIfx_collval = record
    ct_coll: TIfx_collection;                     // collection_t for collection/ROW
    ct_child: PValue;                             // 1st element in the collection/ROW
  end;

  {------------------------------------------------------------------------------}
    // Value types


      // !null && blob type
      //* #define ISBLOBVALUE(val)	((val).v_ind != -1 && ISBLOBTYPE((val).v_type))

  rowvaluet = record
    dummy: Pointer;
  end;
  TRow_desc = rowvaluet;
  TRow_value = rowvaluet;


  // col_t cd_coll_desc cache of cl_*typeinfo
  // and cl_data for val{load/store/ldout}

  _coll_desc = record
    cld_typeinfo: PIfx_cltypeinfo;                // collection cl_svr_typeinfo
    cld_typesize: int4;                           // size of typeinfo
  end;
  TColl_desc = _coll_desc;


  // vchar_t is shared by the value_t and udt_t

  _vchar = record
    // VCHAR_COMMON_HDR
    vcp: PChar;                                   // data start
    vlen: int4;                                   // data length
    vflgs: int2;                                  // flags - see below
    valign: int2;                                 // UDT (SQLROW, SQLUDTFIXED/VAR) alignment
    // end of VCHAR_COMMON_HDR

    vidx: int4;                                   // string+UDT: data block size
    vsstart: int4;                                // substring start for 4GL-RDS
    vsend: int4;                                  // substring end for 4GL-RDS
    fixedLen: int4;                               // Length of fixedStr
    vbyvaluedata: int4;                           // data store for byvalue UDTs
    fixedStr: PChar;                              // Fixed str for FSSEARCH
    shiftTbl: PByte;                              // Shift table for FSSEARCH
  end;
  Tvchar = _vchar;

  {------------------------------------------------------------------------------}

  Tvdecstruct = record
    vdec: TDec;                                   // SQLDECIMAL
    vtme: record
      case Byte of
        0: (vdatetime: TDTime);
        1: (vintrvl: TIntrvl);
    end;
  end;

  Tvrowstruct = record
    // VCHAR_COMMON_HDR
    vcp: PChar;                                   // data start
    vlen: int4;                                   // data length
    vflgs: int2;                                  // flags - see below
    valign: int2;                                 // UDT (SQLROW, SQLUDTFIXED/VAR) alignment
    // end of VCHAR_COMMON_HDR

    vrow: TRow_value;                             // row descriptor and data
  end;

  value = record
    v_type: SmallInt;
    v_ind: SmallInt;                              // null indicator
    v_xid: int4;
    v_prec: SmallInt;                             // decimal precision

    v_val: record
      case SmallInt of                            //  depending on v_type
        0: (vchar: Tvchar);                       // char and udts
        1: (vint: mint);                          // SQLSMINT
        2: (vlng: int4);                          // SQLINT
        3: (vint8: TIfx_int8);                    // SQLINT8
        4: (vflo: Single);                        // SQLSMFLOAT
        5: (vdub: Double);                        // SQLFLOAT
        6: (vdecstruct: Tvdecstruct);
        7: (vaddr: array[0..MAXADDR] of SmallInt); // 4GL address modifiers
        8: (vtblob: Ttblob);                      // BLOB as stored in tuple
        9: (vlocator: PLoc);                      // blobs locator
        10: (vcollection: TIfx_collection);       // collection
        11: (vtree: TIfx_collval);                // value_t tree of collection/ROW
        12: (vrowstruct: Tvrowstruct);            // struct for row values
    end;
  end;

  TValue = value;

  CASTVALP = PValue;

implementation

end.